#ifndef __MAIN_H__
#define __MAIN_H__

#include <chrono>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <filesystem>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <sstream>

using namespace std;
using namespace std::chrono;
using namespace cv;

int gray_thres1;
int gray_thres2;
int area_min;
int epsilon1;
int epsilon2;

struct result {
  int id = -1;
  std::vector<cv::Point> points;
  double x;
};

int dOffset;

cv::dnn::Net net;

// a4 sqrt2/1
int hwr_min = 12;
int hwr_max = 15;
// TODO recovery a4 size
#define A4_WIDTH 162 * 2  // 0.5mm /px
#define A4_HEIGHT 248 * 2 // 0.5mm /px
// TL TR BR BL
std::vector<cv::Point2f> a4Vertices = {
    cv::Point2f(0, 0), cv::Point2f(A4_WIDTH, 0),
    cv::Point2f(A4_WIDTH, A4_HEIGHT), cv::Point2f(0, A4_HEIGHT)};

std::vector<cv::Point3f> objectPoints;
#define A4_WIDTH_M 0.170 // unit m
#define A4_HEIGHT_M 0.257

struct int_param {
  std::string name;
  int &value;
  int default_value;
  int max;
};

std::vector<int_param> int_params_list = //
    {{"gray_thres1", gray_thres1, 100, 255},
     {"gray_thres2", gray_thres2, 100, 255},
     {"hwr_min", hwr_min, 12, 100},
     {"hwr_max", hwr_max, 40, 100},
     {"area_min", area_min, 10000, 100000},
     {"epsilon1", epsilon1, 150, 1000},
     {"epsilon2", epsilon2, 10, 1000},
     {"dOffset", dOffset, 10, 10000}};

void init();

void createTrackbars();

std::vector<cv::Point2f> sortRectanglePoints(cv::Point2f vertices[4]);

bool isTriangle(const vector<cv::Point> &triangle);

void completeRect(std::vector<cv::Point> &rect);

cv::Mat getRectMat(const cv::Mat &img, const cv::RotatedRect &rotateRect,
                   int size);

int digitalDetect(cv::Mat &img, int size);

int forwardStatic(cv::Mat &img, int size, int times);

void completeHiddenRect(const vector<cv::Point> &approx, const int index1,
                        const int index2, vector<cv::Point> &rect);

cv::Point2f computeIntersection(cv::Point2f p1, cv::Point2f dir1,
                                cv::Point2f p2, cv::Point2f dir2);

void ensureRectOrder(vector<cv::Point> &rect);
#endif // __MAIN_H__